<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=2">
<meta name="theme-color" content="#222">
<meta name="generator" content="Hexo 4.2.1">
  <link rel="apple-touch-icon" sizes="180x180" href="/images/apple-touch-icon-next.png">
  <link rel="icon" type="image/png" sizes="32x32" href="/images/%E6%AD%A6%E6%B1%8932x32.png">
  <link rel="icon" type="image/png" sizes="16x16" href="/images/%E6%AD%A6%E6%B1%8916x16.png">
  <link rel="mask-icon" href="/images/logo.svg" color="#222">

<link rel="stylesheet" href="/css/main.css">


<link rel="stylesheet" href="/lib1/font-awesome/css/all.min.css">
  <link rel="stylesheet" href="/lib1/pace/pace-theme-center-simple.min.css">
  <script src="/lib1/pace/pace.min.js"></script>

<script id="hexo-configurations">
    var NexT = window.NexT || {};
    var CONFIG = {"hostname":"example.com","root":"/","scheme":"Gemini","version":"7.8.0","exturl":false,"sidebar":{"position":"left","display":"post","padding":18,"offset":12,"onmobile":false},"copycode":{"enable":true,"show_result":true,"style":null},"back2top":{"enable":true,"sidebar":false,"scrollpercent":false},"bookmark":{"enable":false,"color":"#222","save":"auto"},"fancybox":false,"mediumzoom":false,"lazyload":false,"pangu":false,"comments":{"style":"tabs","active":null,"storage":true,"lazyload":false,"nav":null},"algolia":{"hits":{"per_page":10},"labels":{"input_placeholder":"Search for Posts","hits_empty":"We didn't find any results for the search: ${query}","hits_stats":"${hits} results found in ${time} ms"}},"localsearch":{"enable":true,"trigger":"auto","top_n_per_article":1,"unescape":false,"preload":false},"motion":{"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"slideDownIn","post_body":"slideDownIn","coll_header":"slideLeftIn","sidebar":"slideUpIn"}},"path":"search.xml"};
  </script>

  <meta name="description" content="前言这篇指南被分成了以下章节。 结构： 结构一节将帮助你了解常见库的格式以及如何为每种格式书写正确的声明文件。 如果你在编辑一个已经存在的文件，那么你可能不需要阅读此章节。 如果你在书写新的声明文件，那么你必须阅读此章节以理解库的不同格式是如何影响声明文件的书写的。 举例： 很多时候，我们只能通过一些示例来了解第三方库是如何工作的，同时我们需要为这样的库书写声明文件。举例一节展示了很多常见的API">
<meta property="og:type" content="article">
<meta property="og:title" content="TypeScript声明文件">
<meta property="og:url" content="http://example.com/2021/12/02/%E7%9B%92%E9%A9%AC%E6%8A%80%E6%9C%AF%E6%A0%88%E5%88%9D%E5%AD%A6/typeScript%E5%A3%B0%E6%98%8E%E6%96%87%E4%BB%B6/index.html">
<meta property="og:site_name" content="Technological Blog">
<meta property="og:description" content="前言这篇指南被分成了以下章节。 结构： 结构一节将帮助你了解常见库的格式以及如何为每种格式书写正确的声明文件。 如果你在编辑一个已经存在的文件，那么你可能不需要阅读此章节。 如果你在书写新的声明文件，那么你必须阅读此章节以理解库的不同格式是如何影响声明文件的书写的。 举例： 很多时候，我们只能通过一些示例来了解第三方库是如何工作的，同时我们需要为这样的库书写声明文件。举例一节展示了很多常见的API">
<meta property="og:locale" content="zh_CN">
<meta property="article:published_time" content="2021-12-02T04:18:39.000Z">
<meta property="article:modified_time" content="2021-11-29T11:27:15.230Z">
<meta property="article:author" content="Li Yudong">
<meta property="article:tag" content="公司技术栈">
<meta name="twitter:card" content="summary">

<link rel="canonical" href="http://example.com/2021/12/02/%E7%9B%92%E9%A9%AC%E6%8A%80%E6%9C%AF%E6%A0%88%E5%88%9D%E5%AD%A6/typeScript%E5%A3%B0%E6%98%8E%E6%96%87%E4%BB%B6/">


<script id="page-configurations">
  // https://hexo.io/docs/variables.html
  CONFIG.page = {
    sidebar: "",
    isHome : false,
    isPost : true,
    lang   : 'zh-CN'
  };
</script>

  <title>TypeScript声明文件 | Technological Blog</title>
  






  <noscript>
  <style>
  .use-motion .brand,
  .use-motion .menu-item,
  .sidebar-inner,
  .use-motion .post-block,
  .use-motion .pagination,
  .use-motion .comments,
  .use-motion .post-header,
  .use-motion .post-body,
  .use-motion .collection-header { opacity: initial; }

  .use-motion .site-title,
  .use-motion .site-subtitle {
    opacity: initial;
    top: initial;
  }

  .use-motion .logo-line-before i { left: initial; }
  .use-motion .logo-line-after i { right: initial; }
  </style>
</noscript>

</head>

<body itemscope itemtype="http://schema.org/WebPage">
  <div class="container use-motion">
    <div class="headband"></div>

    <header class="header" itemscope itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-brand-container">
  <div class="site-nav-toggle">
    <div class="toggle" aria-label="切换导航栏">
      <span class="toggle-line toggle-line-first"></span>
      <span class="toggle-line toggle-line-middle"></span>
      <span class="toggle-line toggle-line-last"></span>
    </div>
  </div>

  <div class="site-meta">

    <a href="/" class="brand" rel="start">
      <span class="logo-line-before"><i></i></span>
      <h1 class="site-title">Technological Blog</h1>
      <span class="logo-line-after"><i></i></span>
    </a>
      <p class="site-subtitle" itemprop="description">IT小白的成长之旅</p>
  </div>

  <div class="site-nav-right">
    <div class="toggle popup-trigger">
        <i class="fa fa-search fa-fw fa-lg"></i>
    </div>
  </div>
</div>




<nav class="site-nav">
  <ul id="menu" class="main-menu menu">
        <li class="menu-item menu-item-about">

    <a href="/about/" rel="section"><i class="user fa-fw"></i>关于</a>

  </li>
        <li class="menu-item menu-item-tags">

    <a href="/tags/" rel="section"><i class="tags fa-fw"></i>标签<span class="badge">18</span></a>

  </li>
        <li class="menu-item menu-item-categories">

    <a href="/categories/" rel="section"><i class="th fa-fw"></i>分类<span class="badge">14</span></a>

  </li>
        <li class="menu-item menu-item-archives">

    <a href="/archives/" rel="section"><i class="archive fa-fw"></i>归档<span class="badge">95</span></a>

  </li>
      <li class="menu-item menu-item-search">
        <a role="button" class="popup-trigger"><i class="fa fa-search fa-fw"></i>搜索
        </a>
      </li>
  </ul>
</nav>



  <div class="search-pop-overlay">
    <div class="popup search-popup">
        <div class="search-header">
  <span class="search-icon">
    <i class="fa fa-search"></i>
  </span>
  <div class="search-input-container">
    <input autocomplete="off" autocapitalize="off"
           placeholder="搜索..." spellcheck="false"
           type="search" class="search-input">
  </div>
  <span class="popup-btn-close">
    <i class="fa fa-times-circle"></i>
  </span>
</div>
<div id="search-result">
  <div id="no-result">
    <i class="fa fa-spinner fa-pulse fa-5x fa-fw"></i>
  </div>
</div>

    </div>
  </div>

</div>
    </header>

    
  <div class="back-to-top">
    <i class="fa fa-arrow-up"></i>
    <span>0%</span>
  </div>

  <a href="https://github.com/tiarmor1" class="github-corner" title="Follow me on GitHub" aria-label="Follow me on GitHub" rel="noopener" target="_blank"><svg width="80" height="80" viewBox="0 0 250 250" aria-hidden="true"><path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z"></path><path d="M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2" fill="currentColor" style="transform-origin: 130px 106px;" class="octo-arm"></path><path d="M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z" fill="currentColor" class="octo-body"></path></svg></a>


    <main class="main">
      <div class="main-inner">
        <div class="content-wrap">
          

          <div class="content post posts-expand">
            

    
  
  

  <article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="http://example.com/2021/12/02/%E7%9B%92%E9%A9%AC%E6%8A%80%E6%9C%AF%E6%A0%88%E5%88%9D%E5%AD%A6/typeScript%E5%A3%B0%E6%98%8E%E6%96%87%E4%BB%B6/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/author.jpg">
      <meta itemprop="name" content="Li Yudong">
      <meta itemprop="description" content="">
    </span>
    
    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="Technological Blog">
    </span>
      <header class="post-header">
        <h1 class="post-title" itemprop="name headline">
          TypeScript声明文件
        </h1>
    
        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-calendar"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>
    
              <time title="创建时间：2021-12-02 12:18:39" itemprop="dateCreated datePublished" datetime="2021-12-02T12:18:39+08:00">2021-12-02</time>
            </span>
              <span class="post-meta-item">
                <span class="post-meta-item-icon">
                  <i class="far fa-calendar-check"></i>
                </span>
                <span class="post-meta-item-text">更新于</span>
                <time title="修改时间：2021-11-29 19:27:15" itemprop="dateModified" datetime="2021-11-29T19:27:15+08:00">2021-11-29</time>
              </span>
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-folder"></i>
              </span>
              <span class="post-meta-item-text">分类于</span>
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/categories/%E7%9B%92%E9%A9%AC%E6%8A%80%E6%9C%AF%E6%A0%88/" itemprop="url" rel="index"><span itemprop="name">盒马技术栈</span></a>
                </span>
            </span>
    
          
    
        </div>
      </header>
    
    
    
    
    <div class="post-body" itemprop="articleBody">
    
      
        <h1 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h1><p>这篇指南被分成了以下章节。</p>
<p>结构：</p>
<p><a href="https://www.tslang.cn/docs/handbook/declaration-files/library-structures.html" target="_blank" rel="noopener">结构</a>一节将帮助你了解常见库的格式以及如何为每种格式书写正确的声明文件。 如果你在编辑一个已经存在的文件，那么你可能不需要阅读此章节。 如果你在书写新的声明文件，那么你必须阅读此章节以理解库的不同格式是如何影响声明文件的书写的。</p>
<p>举例：</p>
<p>很多时候，我们只能通过一些示例来了解第三方库是如何工作的，同时我们需要为这样的库书写声明文件。<a href="https://www.tslang.cn/docs/handbook/declaration-files/by-example.html" target="_blank" rel="noopener">举例</a>一节展示了很多常见的API模式以及如何为它们书写声明文件。 这篇指南是针对TypeScript初学者的，他们可能还不了解TypeScript里的所有语言结构。</p>
<p>规范：</p>
<p>声明文件里有很多常见的错误是很容易避免的。<a href="https://www.tslang.cn/docs/handbook/declaration-files/do-s-and-don-ts.html" target="_blank" rel="noopener">规范</a>一节指出了常见的错误， 描述了如何发现它们， 与怎样去修复。 每个人都要阅读这个章节以了解如何避免常见错误。</p>
<p>深入：</p>
<p>对于那些对声明文件底层工作机制感兴趣的老手们，<a href="https://www.tslang.cn/docs/handbook/declaration-files/deep-dive.html" target="_blank" rel="noopener">深入</a>一节解释了很多高级书写声明文件的高级概念， 以及展示了如何利用这些概念来创建整洁和直观的声明文件。</p>
<p>模版：</p>
<p>在<a href="https://www.tslang.cn/docs/handbook/declaration-files/templates.html" target="_blank" rel="noopener">模版</a>一节里，你能找到一些声明文件，它们可以帮助你快速开始 当你在书写一个新声明文件的时候。 参考<a href="https://www.tslang.cn/docs/handbook/declaration-files/library-structures.html" target="_blank" rel="noopener">结构</a>这篇文档来找到应该使用哪个模版文件。</p>
<p>发布到npm：</p>
<p><a href="https://www.tslang.cn/docs/handbook/declaration-files/publishing.html" target="_blank" rel="noopener">发布</a>一节讲解了如何发布声明文件为npm包，及如何管理包的依赖。</p>
<p>查找与安装声明文件：</p>
<p>对于JavaScript库的使用者来讲，<a href="https://www.tslang.cn/docs/handbook/declaration-files/consumption.html" target="_blank" rel="noopener">使用</a>一节提供了一些简单步骤来定位与安装相应的声明文件。</p>
<h1 id="结构"><a href="#结构" class="headerlink" title="结构"></a>结构</h1><p>一般来讲，你<em>组织</em>声明文件的方式取决于库是如何被使用的。 在JavaScript中一个库有很多使用方式，这就需要你书写声明文件去匹配它们。 这篇指南涵盖了如何识别常见库的模式，和怎样书写符合相应模式的声明文件。</p>
<p>针对每种主要的库的组织模式，在<a href="https://www.tslang.cn/docs/handbook/declaration-files/templates.html" target="_blank" rel="noopener">模版</a>一节都有对应的文件。 你可以利用它们帮助你快速上手。</p>
<h2 id="识别库的类型"><a href="#识别库的类型" class="headerlink" title="识别库的类型"></a>识别库的类型</h2><p>首先，我们先看一下TypeScript声明文件能够表示的库的类型。 这里会简单展示每种类型的库的使用方式，如何去书写，还有一些真实案例。识别库的类型是书写声明文件的第一步。 我们将会给出一些提示，关于怎样通过库的 <em>使用方法</em>及其<em>源码</em>来识别库的类型。 根据库的文档及组织结构不同，这两种方式可能一个会比另外的那个简单一些。 我们推荐你使用任意你喜欢的方式。</p>
<p><strong>全局库</strong></p>
<p><em>全局</em>库是指能在全局命名空间下访问的（例如：不需要使用任何形式的<code>import</code>）。 许多库都是简单的暴露出一个或多个全局变量。 比如，如果你使用过 <a href="https://jquery.com/" target="_blank" rel="noopener">jQuery</a>，<code>$</code>变量可以被够简单的引用：</p>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$(() =&gt; &#123; <span class="built_in">console</span>.log(<span class="string">'hello!'</span>); &#125; );</span><br></pre></td></tr></table></figure>

<p>你经常会在全局库的指南文档上看到如何在HTML里用脚本标签引用库：</p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">"http://a.great.cdn.for/someLib.js"</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>目前，大多数流行的全局访问型库实际上都以UMD库的形式进行书写（见后文）。 UMD库的文档很难与全局库文档两者之间难以区分。 在书写全局声明文件前，一定要确认一下库是否真的不是UMD。</p>
<p><strong>从代码上识别全局库</strong></p>
<p>全局库的代码通常都十分简单。 一个全局的“Hello, world”库可能是这样的：</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">createGreeting</span>(<span class="params">s</span>) </span>&#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="string">"Hello, "</span> + s;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>或这样：</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">window</span>.createGreeting = <span class="function"><span class="keyword">function</span>(<span class="params">s</span>) </span>&#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="string">"Hello, "</span> + s;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>当你查看全局库的源代码时，你通常会看到：</p>
<ul>
<li>顶级的<code>var</code>语句或<code>function</code>声明</li>
<li>一个或多个赋值语句到<code>window.someName</code></li>
<li>假设DOM原始值像<code>document</code>或<code>window</code>是存在的</li>
</ul>
<p>你<em>不会</em>看到：</p>
<ul>
<li>检查是否使用或如何使用模块加载器，比如<code>require</code>或<code>define</code></li>
<li>CommonJS/Node.js风格的导入如<code>var fs = require(&quot;fs&quot;);</code></li>
<li><code>define(...)</code>调用</li>
<li>文档里说明了如何去<code>require</code>或导入这个库</li>
</ul>
<p>全局库的例子：</p>
<p>由于把一个全局库转变成UMD库是非常容易的，所以很少流行的库还再使用全局的风格。 然而，小型的且需要DOM（或 <em>没有</em>依赖）的库可能还是全局类型的。</p>
<p>模版文件<a href="https://www.tslang.cn/docs/handbook/declaration-files/templates/global-d-ts.html" target="_blank" rel="noopener"><code>global.d.ts</code></a>定义了<code>myLib</code>库作为例子。 一定要阅读 <a href="https://www.tslang.cn/docs/handbook/declaration-files/library-structures.html#preventing-name-conflicts" target="_blank" rel="noopener">“防止命名冲突”补充说明</a>。</p>
<p><strong>模块化库</strong>：</p>
<p>一些库只能工作在模块加载器的环境下。 比如，像 <code>express</code>只能在Node.js里工作所以必须使用CommonJS的<code>require</code>函数加载。ECMAScript 2015（也就是ES2015，ECMAScript 6或ES6），CommonJS和RequireJS具有相似的<em>导入</em>一个<em>模块</em>的表示方法。 例如，对于JavaScript CommonJS （Node.js），有下面的代码</p>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> fs = <span class="built_in">require</span>(<span class="string">"fs"</span>);</span><br></pre></td></tr></table></figure>

<p>对于TypeScript或ES6，<code>import</code>关键字也具有相同的作用：</p>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> fs = <span class="built_in">require</span>(<span class="string">"fs"</span>);</span><br></pre></td></tr></table></figure>

<p>你通常会在模块化库的文档里看到如下说明：</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> someLib = <span class="built_in">require</span>(<span class="string">'someLib'</span>);</span><br></pre></td></tr></table></figure>

<p>或</p>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">define(..., [<span class="string">'someLib'</span>], <span class="function"><span class="keyword">function</span>(<span class="params">someLib</span>) </span>&#123;</span><br><span class="line"></span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure>

<p>与全局模块一样，你也可能会在UMD模块的文档里看到这些例子，因此要仔细查看源码和文档。</p>
<p><strong>从代码上识别模块化库</strong>：</p>
<p>模块库至少会包含下列具有代表性的条目之一：</p>
<ul>
<li>无条件的调用<code>require</code>或<code>define</code></li>
<li>像<code>import * as a from &#39;b&#39;;</code> or <code>export c;</code>这样的声明</li>
<li>赋值给<code>exports</code>或<code>module.exports</code></li>
</ul>
<p>它们极少包含：</p>
<ul>
<li>对<code>window</code>或<code>global</code>的赋值</li>
</ul>
<p>模块化库的例子：</p>
<p>许多流行的Node.js库都是这种模块化的，例如<a href="http://expressjs.com/" target="_blank" rel="noopener"><code>express</code></a>，<a href="http://gulpjs.com/" target="_blank" rel="noopener"><code>gulp</code></a>和 <a href="https://github.com/request/request" target="_blank" rel="noopener"><code>request</code></a>。</p>
<p><em><strong>UMD</strong></em>：</p>
<p><em>UMD</em>模块是指那些既可以作为模块使用（通过导入）又可以作为全局（在没有模块加载器的环境里）使用的模块。 许多流行的库，比如 <a href="http://momentjs.com/" target="_blank" rel="noopener">Moment.js</a>，就是这样的形式。 比如，在Node.js或RequireJS里，你可以这样写：</p>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> moment = <span class="built_in">require</span>(<span class="string">"moment"</span>);</span><br><span class="line"><span class="built_in">console</span>.log(moment.format());</span><br></pre></td></tr></table></figure>

<p>然而在纯净的浏览器环境里你也可以这样写：</p>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">console</span>.log(moment.format());</span><br></pre></td></tr></table></figure>

<p>识别UMD库</p>
<p><a href="https://github.com/umdjs/umd" target="_blank" rel="noopener">UMD模块</a>会检查是否存在模块加载器环境。 这是非常形容观察到的模块，它们会像下面这样：</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">(<span class="function"><span class="keyword">function</span> (<span class="params">root, factory</span>) </span>&#123;</span><br><span class="line">    <span class="keyword">if</span> (<span class="keyword">typeof</span> define === <span class="string">"function"</span> &amp;&amp; define.amd) &#123;</span><br><span class="line">        define([<span class="string">"libName"</span>], factory);</span><br><span class="line">    &#125; <span class="keyword">else</span> <span class="keyword">if</span> (<span class="keyword">typeof</span> <span class="built_in">module</span> === <span class="string">"object"</span> &amp;&amp; <span class="built_in">module</span>.exports) &#123;</span><br><span class="line">        <span class="built_in">module</span>.exports = factory(<span class="built_in">require</span>(<span class="string">"libName"</span>));</span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">        root.returnExports = factory(root.libName);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;(<span class="keyword">this</span>, <span class="function"><span class="keyword">function</span> (<span class="params">b</span>) </span>&#123;</span><br></pre></td></tr></table></figure>

<p>如果你在库的源码里看到了<code>typeof define</code>，<code>typeof window</code>，或<code>typeof module</code>这样的测试，尤其是在文件的顶端，那么它几乎就是一个UMD库。</p>
<p>UMD库的文档里经常会包含通过<code>require</code>“在Node.js里使用”例子， 和“在浏览器里使用”的例子，展示如何使用 <code>&lt;script&gt;</code>标签去加载脚本。</p>
<p>UMD库的例子</p>
<p>大多数流行的库现在都能够被当成UMD包。 比如 <a href="https://jquery.com/" target="_blank" rel="noopener">jQuery</a>,<a href="http://momentjs.com/" target="_blank" rel="noopener">Moment.js</a>,<a href="https://lodash.com/" target="_blank" rel="noopener">lodash</a>和许多其它的。</p>
<p>模版</p>
<p>针对模块有三种可用的模块， <a href="https://www.tslang.cn/docs/handbook/declaration-files/templates/module-d-ts.html" target="_blank" rel="noopener"><code>module.d.ts</code></a>, <a href="https://www.tslang.cn/docs/handbook/declaration-files/templates/module-class-d-ts.html" target="_blank" rel="noopener"><code>module-class.d.ts</code></a> and <a href="https://www.tslang.cn/docs/handbook/declaration-files/templates/module-function-d-ts.html" target="_blank" rel="noopener"><code>module-function.d.ts</code></a>.</p>
<p>使用<a href="https://www.tslang.cn/docs/handbook/declaration-files/templates/module-function-d-ts.html" target="_blank" rel="noopener"><code>module-function.d.ts</code></a>，如果模块能够作为函数<em>调用</em>。</p>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> x = <span class="built_in">require</span>(<span class="string">"foo"</span>);</span><br><span class="line"><span class="comment">// Note: calling 'x' as a function</span></span><br><span class="line"><span class="keyword">var</span> y = x(<span class="number">42</span>);</span><br></pre></td></tr></table></figure>

<p>一定要阅读<a href="https://www.tslang.cn/docs/handbook/declaration-files/library-structures.html#the-impact-of-es6-on-module-call-signatures" target="_blank" rel="noopener">补充说明： “ES6模块调用签名的影响”</a></p>
<p>使用<a href="https://www.tslang.cn/docs/handbook/declaration-files/templates/module-class-d-ts.html" target="_blank" rel="noopener"><code>module-class.d.ts</code></a>如果模块能够使用<code>new</code>来<em>构造</em>：</p>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> x = <span class="built_in">require</span>(<span class="string">"bar"</span>);</span><br><span class="line"><span class="comment">// Note: using 'new' operator on the imported variable</span></span><br><span class="line"><span class="keyword">var</span> y = <span class="keyword">new</span> x(<span class="string">"hello"</span>);</span><br></pre></td></tr></table></figure>

<p>相同的<a href="https://www.tslang.cn/docs/handbook/declaration-files/library-structures.html#the-impact-of-es6-on-module-plugins" target="_blank" rel="noopener">补充说明</a>作用于这些模块。</p>
<p>如果模块不能被调用或构造，使用<a href="https://www.tslang.cn/docs/handbook/declaration-files/templates/module-d-ts.html" target="_blank" rel="noopener"><code>module.d.ts</code></a>文件。</p>
<p><em>模块插件</em>或<em>UMD插件</em>：</p>
<p>一个<em>模块插件</em>可以改变一个模块的结构（UMD或模块）。 例如，在Moment.js里， <code>moment-range</code>添加了新的<code>range</code>方法到<code>monent</code>对象。</p>
<p>对于声明文件的目标，我们会写相同的代码不论被改变的模块是一个纯粹的模块还是UMD模块。</p>
<p>模版：</p>
<p>使用<a href="https://www.tslang.cn/docs/handbook/declaration-files/templates/module-plugin-d-ts.html" target="_blank" rel="noopener"><code>module-plugin.d.ts</code></a>模版。</p>
<p><em>全局插件</em>：</p>
<p>一个<em>全局插件</em>是全局代码，它们会改变全局对象的结构。 对于 <em>全局修改的模块</em>，在运行时存在冲突的可能。</p>
<p>比如，一些库往<code>Array.prototype</code>或<code>String.prototype</code>里添加新的方法。</p>
<p>识别全局插件：</p>
<p>全局通常很容易地从它们的文档识别出来。</p>
<p>你会看到像下面这样的例子：</p>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> x = <span class="string">"hello, world"</span>;</span><br><span class="line"><span class="comment">// Creates new methods on built-in types</span></span><br><span class="line"><span class="built_in">console</span>.log(x.startsWithHello());</span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> y = [<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>];</span><br><span class="line"><span class="comment">// Creates new methods on built-in types</span></span><br><span class="line"><span class="built_in">console</span>.log(y.reverseAndSort());</span><br></pre></td></tr></table></figure>

<p>模版：</p>
<p>使用<a href="https://www.tslang.cn/docs/handbook/declaration-files/templates/global-plugin-d-ts.html" target="_blank" rel="noopener"><code>global-plugin.d.ts</code></a>模版。</p>
<p><em>全局修改的模块</em>：</p>
<p>当一个<em>全局修改的模块</em>被导入的时候，它们会改变全局作用域里的值。 比如，存在一些库它们添加新的成员到 <code>String.prototype</code>当导入它们的时候。 这种模式很危险，因为可能造成运行时的冲突， 但是我们仍然可以为它们书写声明文件。</p>
<p>识别全局修改的模块</p>
<p>全局修改的模块通常可以很容易地从它们的文档识别出来。 通常来讲，它们与全局插件相似，但是需要 <code>require</code>调用来激活它们的效果。</p>
<p>你可能会看到像下面这样的文档:</p>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 'require' call that doesn't use its return value</span></span><br><span class="line"><span class="keyword">var</span> unused = <span class="built_in">require</span>(<span class="string">"magic-string-time"</span>);</span><br><span class="line"><span class="comment">/* or */</span></span><br><span class="line"><span class="built_in">require</span>(<span class="string">"magic-string-time"</span>);</span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> x = <span class="string">"hello, world"</span>;</span><br><span class="line"><span class="comment">// Creates new methods on built-in types</span></span><br><span class="line"><span class="built_in">console</span>.log(x.startsWithHello());</span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> y = [<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>];</span><br><span class="line"><span class="comment">// Creates new methods on built-in types</span></span><br><span class="line"><span class="built_in">console</span>.log(y.reverseAndSort());</span><br></pre></td></tr></table></figure>

<p>模版：</p>
<p>使用<a href="https://www.tslang.cn/docs/handbook/declaration-files/templates/global-modifying-module-d-ts.html" target="_blank" rel="noopener"><code>global-modifying-module.d.ts</code></a>模版。</p>
<h2 id="使用依赖"><a href="#使用依赖" class="headerlink" title="使用依赖"></a>使用依赖</h2><p>可能会有以下几种依赖。</p>
<p>依赖全局库：</p>
<p>如果你的库依赖于某个全局库，使用<code>/// &lt;reference types=&quot;...&quot; /&gt;</code>指令：</p>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/// &lt;reference types="someLib" /&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">getThing</span>(<span class="params"></span>): <span class="title">someLib</span>.<span class="title">thing</span></span>;</span><br></pre></td></tr></table></figure>

<p>依赖模块：</p>
<p>如果你的库依赖于模块，使用<code>import</code>语句：</p>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> * <span class="keyword">as</span> moment <span class="keyword">from</span> <span class="string">"moment"</span>;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">getThing</span>(<span class="params"></span>): <span class="title">moment</span></span>;</span><br></pre></td></tr></table></figure>

<p>依赖UMD库：</p>
<p>从全局库：</p>
<p>如果你的全局库依赖于某个UMD模块，使用<code>/// &lt;reference types</code>指令：</p>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/// &lt;reference types="moment" /&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">getThing</span>(<span class="params"></span>): <span class="title">moment</span></span>;</span><br></pre></td></tr></table></figure>

<p>从一个模块或UMD库：</p>
<p>如果你的模块或UMD库依赖于一个UMD库，使用<code>import</code>语句：</p>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> * <span class="keyword">as</span> someLib <span class="keyword">from</span> <span class="string">'someLib'</span>;</span><br></pre></td></tr></table></figure>

<p><em>不要</em>使用<code>/// &lt;reference</code>指令去声明UMD库的依赖！</p>
<h2 id="补充说明"><a href="#补充说明" class="headerlink" title="补充说明"></a>补充说明</h2><p>防止命名冲突：</p>
<p>注意，在书写全局声明文件时，允许在全局作用域里定义很多类型。 我们十分不建义这样做，当一个工程里有许多声明文件时，它会导致无法处理的命名冲突。</p>
<p>一个简单的规则是使用库定义的全局变量名来声明命名空间类型。 比如，库定义了一个全局的值 <code>cats</code>，你可以这样写</p>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">declare</span> <span class="keyword">namespace</span> cats &#123;</span><br><span class="line">    <span class="keyword">interface</span> KittySettings &#123; &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p><em>不要</em></p>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// at top-level</span></span><br><span class="line"><span class="keyword">interface</span> CatsKittySettings &#123; &#125;</span><br></pre></td></tr></table></figure>

<p>这样也保证了库在转换成UMD的时候没有任何的破坏式改变，对于声明文件用户来说。</p>
<p>ES6模块插件的影响：</p>
<p>一些插件添加或修改已存在的顶层模块的导出部分。 当然这在CommonJS和其它加载器里是允许的，ES模块被当作是不可改变的因此这种模式就不可行了。 因为TypeScript是能不预知加载器类型的，所以没没在编译时保证，但是开发者如果要转到ES6模块加载器上应该注意这一点。</p>
<p>ES6模块调用签名的影响：</p>
<p>很多流行库，比如Express，暴露出自己作为可以调用的函数。 比如，典型的Express使用方法如下：</p>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> exp = <span class="built_in">require</span>(<span class="string">"express"</span>);</span><br><span class="line"><span class="keyword">var</span> app = exp();</span><br></pre></td></tr></table></figure>

<p>在ES6模块加载器里，顶层的对象（这里以<code>exp</code>导入）只能具有属性； 顶层的模块对象 <em>永远不能</em>被调用。 十分常见的解决方法是定义一个 <code>default</code>导出到一个可调用的/可构造的对象； 一会模块加载器助手工具能够自己探测到这种情况并且使用 <code>default</code>导出来替换顶层对象。</p>
<h1 id="举例"><a href="#举例" class="headerlink" title="举例"></a>举例</h1><p>这篇指南的目的是教你如何书写高质量的TypeScript声明文件。 我们在这里会展示一些API的文档，还有它们的使用示例， 并且阐述了如何为它们书写声明文件。</p>
<p>这些例子是按复杂度递增的顺序组织的。</p>
<ul>
<li><a href="https://www.tslang.cn/docs/handbook/declaration-files/by-example.html#global-variables" target="_blank" rel="noopener">全局变量</a></li>
<li><a href="https://www.tslang.cn/docs/handbook/declaration-files/by-example.html#global-functions" target="_blank" rel="noopener">全局函数</a></li>
<li><a href="https://www.tslang.cn/docs/handbook/declaration-files/by-example.html#objects-with-properties" target="_blank" rel="noopener">带属性的对象</a></li>
<li><a href="https://www.tslang.cn/docs/handbook/declaration-files/by-example.html#overloaded-functions" target="_blank" rel="noopener">函数重载</a></li>
<li><a href="https://www.tslang.cn/docs/handbook/declaration-files/by-example.html#reusable-types-interfaces" target="_blank" rel="noopener">可重用类型（接口）</a></li>
<li><a href="https://www.tslang.cn/docs/handbook/declaration-files/by-example.html#reusable-types-type-aliases" target="_blank" rel="noopener">可重用类型（类型别名）</a></li>
<li><a href="https://www.tslang.cn/docs/handbook/declaration-files/by-example.html#organizing-types" target="_blank" rel="noopener">组织类型</a></li>
<li><a href="https://www.tslang.cn/docs/handbook/declaration-files/by-example.html#classes" target="_blank" rel="noopener">类</a></li>
</ul>
<h2 id="例子"><a href="#例子" class="headerlink" title="例子"></a>例子</h2><h3 id="全局变量"><a href="#全局变量" class="headerlink" title="全局变量"></a>全局变量</h3><p><em>文档</em></p>
<blockquote>
<p>全局变量<code>foo</code>包含了存在组件总数。</p>
</blockquote>
<p><em>代码</em></p>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">console</span>.log(<span class="string">"Half the number of widgets is "</span> + (foo / <span class="number">2</span>));</span><br></pre></td></tr></table></figure>

<p><em>声明</em></p>
<p>使用<code>declare var</code>声明变量。 如果变量是只读的，那么可以使用 <code>declare const</code>。 你还可以使用 <code>declare let</code>如果变量拥有块级作用域。</p>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/** 组件总数 */</span></span><br><span class="line"><span class="keyword">declare</span> <span class="keyword">var</span> foo: <span class="built_in">number</span>;</span><br></pre></td></tr></table></figure>

<h3 id="全局函数"><a href="#全局函数" class="headerlink" title="全局函数"></a>全局函数</h3><p><em>文档</em></p>
<blockquote>
<p>用一个字符串参数调用<code>greet</code>函数向用户显示一条欢迎信息。</p>
</blockquote>
<p><em>代码</em></p>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">greet(<span class="string">"hello, world"</span>);</span><br></pre></td></tr></table></figure>

<p><em>声明</em></p>
<p>使用<code>declare function</code>声明函数。</p>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">declare</span> <span class="function"><span class="keyword">function</span> <span class="title">greet</span>(<span class="params">greeting: <span class="built_in">string</span></span>): <span class="title">void</span></span>;</span><br></pre></td></tr></table></figure>

<h3 id="带属性的对象"><a href="#带属性的对象" class="headerlink" title="带属性的对象"></a>带属性的对象</h3><p><em>文档</em></p>
<blockquote>
<p>全局变量<code>myLib</code>包含一个<code>makeGreeting</code>函数， 还有一个属性 <code>numberOfGreetings</code>指示目前为止欢迎数量。</p>
</blockquote>
<p><em>代码</em></p>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> result = myLib.makeGreeting(<span class="string">"hello, world"</span>);</span><br><span class="line"><span class="built_in">console</span>.log(<span class="string">"The computed greeting is:"</span> + result);</span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> count = myLib.numberOfGreetings;</span><br></pre></td></tr></table></figure>

<p><em>声明</em></p>
<p>使用<code>declare namespace</code>描述用点表示法访问的类型或值。</p>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">declare</span> <span class="keyword">namespace</span> myLib &#123;</span><br><span class="line">    <span class="function"><span class="keyword">function</span> <span class="title">makeGreeting</span>(<span class="params">s: <span class="built_in">string</span></span>): <span class="title">string</span></span>;</span><br><span class="line">    <span class="keyword">let</span> numberOfGreetings: <span class="built_in">number</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h3 id="函数重载"><a href="#函数重载" class="headerlink" title="函数重载"></a>函数重载</h3><p><em>文档</em></p>
<blockquote>
<p><code>getWidget</code>函数接收一个数字，返回一个组件，或接收一个字符串并返回一个组件数组。</p>
</blockquote>
<p><em>代码</em></p>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> x: Widget = getWidget(<span class="number">43</span>);</span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> arr: Widget[] = getWidget(<span class="string">"all of them"</span>);</span><br></pre></td></tr></table></figure>

<p><em>声明</em></p>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">declare</span> <span class="function"><span class="keyword">function</span> <span class="title">getWidget</span>(<span class="params">n: <span class="built_in">number</span></span>): <span class="title">Widget</span></span>;</span><br><span class="line"><span class="keyword">declare</span> <span class="function"><span class="keyword">function</span> <span class="title">getWidget</span>(<span class="params">s: <span class="built_in">string</span></span>): <span class="title">Widget</span>[]</span>;</span><br></pre></td></tr></table></figure>

<h3 id="可重用类型（接口）"><a href="#可重用类型（接口）" class="headerlink" title="可重用类型（接口）"></a>可重用类型（接口）</h3><p><em>文档</em></p>
<blockquote>
<p>当指定一个欢迎词时，你必须传入一个<code>GreetingSettings</code>对象。 这个对象具有以下几个属性：</p>
<p>1- greeting：必需的字符串</p>
<p>2- duration: 可靠的时长（毫秒表示）</p>
<p>3- color: 可选字符串，比如‘#ff00ff’</p>
</blockquote>
<p><em>代码</em></p>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">greet(&#123;</span><br><span class="line">  greeting: <span class="string">"hello world"</span>,</span><br><span class="line">  duration: <span class="number">4000</span></span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure>

<p><em>声明</em></p>
<p>使用<code>interface</code>定义一个带有属性的类型。</p>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">interface</span> GreetingSettings &#123;</span><br><span class="line">  greeting: <span class="built_in">string</span>;</span><br><span class="line">  duration?: <span class="built_in">number</span>;</span><br><span class="line">  color?: <span class="built_in">string</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">declare</span> <span class="function"><span class="keyword">function</span> <span class="title">greet</span>(<span class="params">setting: GreetingSettings</span>): <span class="title">void</span></span>;</span><br></pre></td></tr></table></figure>

<h3 id="可重用类型（类型别名）"><a href="#可重用类型（类型别名）" class="headerlink" title="可重用类型（类型别名）"></a>可重用类型（类型别名）</h3><p><em>文档</em></p>
<blockquote>
<p>在任何需要欢迎词的地方，你可以提供一个<code>string</code>，一个返回<code>string</code>的函数或一个<code>Greeter</code>实例。</p>
</blockquote>
<p><em>代码</em></p>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">getGreeting</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="string">"howdy"</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">class</span> MyGreeter <span class="keyword">extends</span> Greeter &#123; &#125;</span><br><span class="line"></span><br><span class="line">greet(<span class="string">"hello"</span>);</span><br><span class="line">greet(getGreeting);</span><br><span class="line">greet(<span class="keyword">new</span> MyGreeter());</span><br></pre></td></tr></table></figure>

<p><em>声明</em></p>
<p>你可以使用类型别名来定义类型的短名：</p>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//type是ts中独有的类型定义</span></span><br><span class="line"><span class="keyword">type</span> GreetingLike = <span class="built_in">string</span> | <span class="function">(<span class="params">(<span class="params"></span>) =&gt; <span class="built_in">string</span></span>) | <span class="params">MyGreeter</span>;</span></span><br><span class="line"><span class="function"></span></span><br><span class="line"><span class="function"><span class="params">declare</span> <span class="params">function</span> <span class="params">greet</span>(<span class="params">g: GreetingLike</span>): <span class="params">void</span>;</span></span><br></pre></td></tr></table></figure>

<h3 id="组织类型"><a href="#组织类型" class="headerlink" title="组织类型"></a>组织类型</h3><p><em>文档</em></p>
<blockquote>
<p><code>greeter</code>对象能够记录到文件或显示一个警告。 你可以为 <code>.log(...)</code>提供LogOptions和为<code>.alert(...)</code>提供选项。</p>
</blockquote>
<p><em>代码</em></p>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> g = <span class="keyword">new</span> Greeter(<span class="string">"Hello"</span>);</span><br><span class="line">g.log(&#123; verbose: <span class="literal">true</span> &#125;);</span><br><span class="line">g.alert(&#123; modal: <span class="literal">false</span>, title: <span class="string">"Current Greeting"</span> &#125;);</span><br></pre></td></tr></table></figure>

<p><em>声明</em></p>
<p>使用命名空间组织类型。</p>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">declare</span> <span class="keyword">namespace</span> GreetingLib &#123;</span><br><span class="line">    <span class="keyword">interface</span> LogOptions &#123;</span><br><span class="line">        verbose?: <span class="built_in">boolean</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">interface</span> AlertOptions &#123;</span><br><span class="line">        modal: <span class="built_in">boolean</span>;</span><br><span class="line">        title?: <span class="built_in">string</span>;</span><br><span class="line">        color?: <span class="built_in">string</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>你也可以在一个声明中创建嵌套的命名空间：</p>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">declare</span> <span class="keyword">namespace</span> GreetingLib.Options &#123;</span><br><span class="line">    <span class="comment">// Refer to via GreetingLib.Options.Log</span></span><br><span class="line">    <span class="keyword">interface</span> Log &#123;</span><br><span class="line">        verbose?: <span class="built_in">boolean</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">interface</span> Alert &#123;</span><br><span class="line">        modal: <span class="built_in">boolean</span>;</span><br><span class="line">        title?: <span class="built_in">string</span>;</span><br><span class="line">        color?: <span class="built_in">string</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h3 id="类"><a href="#类" class="headerlink" title="类"></a>类</h3><p><em>文档</em></p>
<blockquote>
<p>你可以通过实例化<code>Greeter</code>对象来创建欢迎词，或者继承<code>Greeter</code>对象来自定义欢迎词。</p>
</blockquote>
<p><em>代码</em></p>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> myGreeter = <span class="keyword">new</span> Greeter(<span class="string">"hello, world"</span>);</span><br><span class="line">myGreeter.greeting = <span class="string">"howdy"</span>;</span><br><span class="line">myGreeter.showGreeting();</span><br><span class="line"></span><br><span class="line"><span class="keyword">class</span> SpecialGreeter <span class="keyword">extends</span> Greeter &#123;</span><br><span class="line">    <span class="keyword">constructor</span>(<span class="params"></span>) &#123;</span><br><span class="line">        <span class="keyword">super</span>(<span class="string">"Very special greetings"</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p><em>声明</em></p>
<p>使用<code>declare class</code>描述一个类或像类一样的对象。 类可以有属性和方法，就和构造函数一样。</p>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">declare</span> <span class="keyword">class</span> Greeter &#123;</span><br><span class="line">    <span class="keyword">constructor</span>(<span class="params">greeting: <span class="built_in">string</span></span>);</span><br><span class="line"></span><br><span class="line">    greeting: <span class="built_in">string</span>;</span><br><span class="line">    showGreeting(): <span class="built_in">void</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h1 id="规范"><a href="#规范" class="headerlink" title="规范"></a>规范</h1><h3 id="普通类型"><a href="#普通类型" class="headerlink" title="普通类型"></a>普通类型</h3><p><code>Number</code>，<code>String</code>，<code>Boolean</code>和<code>Object</code>：</p>
<p><em>不要</em>使用如下类型<code>Number</code>，<code>String</code>，<code>Boolean</code>或<code>Object</code>。 这些类型指的是非原始的装盒对象，它们几乎没在JavaScript代码里正确地使用过。</p>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/* 错误 */</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">reverse</span>(<span class="params">s: <span class="built_in">String</span></span>): <span class="title">String</span></span>;</span><br></pre></td></tr></table></figure>

<p><em>应该</em>使用类型<code>number</code>，<code>string</code>，and <code>boolean</code>。</p>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/* OK */</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">reverse</span>(<span class="params">s: <span class="built_in">string</span></span>): <span class="title">string</span></span>;</span><br></pre></td></tr></table></figure>

<p>使用非原始的<code>object</code>类型来代替<code>Object</code> （<a href="https://www.tslang.cn/docs/release-notes/typescript-2.2.html#object-type" target="_blank" rel="noopener">TypeScript 2.2新增特性</a>）</p>
<p>泛型：</p>
<p><em>不要</em>定义一个从来没使用过其类型参数的泛型类型。 了解详情 <a href="https://github.com/Microsoft/TypeScript/wiki/FAQ#why-doesnt-type-inference-work-on-this-interface-interface-foot---" target="_blank" rel="noopener">TypeScript FAQ page</a>。</p>
<h3 id="回调函数类型"><a href="#回调函数类型" class="headerlink" title="回调函数类型"></a>回调函数类型</h3><p>回调函数返回值类型：</p>
<p><em>不要</em>为返回值被忽略的回调函数设置一个<code>any</code>类型的返回值类型：</p>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/* 错误 */</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">fn</span>(<span class="params">x: () =&gt; <span class="built_in">any</span></span>) </span>&#123;</span><br><span class="line">    x();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p><em>应该</em>给返回值被忽略的回调函数设置<code>void</code>类型的返回值类型：</p>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/* OK */</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">fn</span>(<span class="params">x: () =&gt; <span class="built_in">void</span></span>) </span>&#123;</span><br><span class="line">    x();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p><em>为什么</em>：使用<code>void</code>相对安全，因为它防止了你不小心使用<code>x</code>的返回值：</p>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">fn</span>(<span class="params">x: () =&gt; <span class="built_in">void</span></span>) </span>&#123;</span><br><span class="line">    <span class="keyword">var</span> k = x(); <span class="comment">// oops! meant to do something else</span></span><br><span class="line">    k.doSomething(); <span class="comment">// error, but would be OK if the return type had been 'any'</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>回调函数里的可选参数：</p>
<p><em>不要</em>在回调函数里使用可选参数除非你真的要这么做：</p>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/* 错误 */</span></span><br><span class="line"><span class="keyword">interface</span> Fetcher &#123;</span><br><span class="line">    getObject(done: <span class="function">(<span class="params">data: <span class="built_in">any</span>, elapsedTime?: <span class="built_in">number</span></span>) =&gt;</span> <span class="built_in">void</span>): <span class="built_in">void</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>这里有一种特殊的意义：<code>done</code>回调函数可能以1个参数或2个参数调用。 代码大概的意思是说这个回调函数不在乎是否有 <code>elapsedTime</code>参数， 但是不需要把这个参数当成可选参数来达到此目的 – 因为总是允许提供一个接收较少参数的回调函数。</p>
<p><em>应该</em>写出回调函数的非可选参数：</p>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/* OK */</span></span><br><span class="line"><span class="keyword">interface</span> Fetcher &#123;</span><br><span class="line">    getObject(done: <span class="function">(<span class="params">data: <span class="built_in">any</span>, elapsedTime: <span class="built_in">number</span></span>) =&gt;</span> <span class="built_in">void</span>): <span class="built_in">void</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>重载与回调函数：</p>
<p><em>不要</em>因为回调函数参数个数不同而写不同的重载：</p>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/* 错误 */</span></span><br><span class="line"><span class="keyword">declare</span> <span class="function"><span class="keyword">function</span> <span class="title">beforeAll</span>(<span class="params">action: () =&gt; <span class="built_in">void</span>, timeout?: <span class="built_in">number</span></span>): <span class="title">void</span></span>;</span><br><span class="line"><span class="keyword">declare</span> <span class="function"><span class="keyword">function</span> <span class="title">beforeAll</span>(<span class="params">action: (done: DoneFn) =&gt; <span class="built_in">void</span>, timeout?: <span class="built_in">number</span></span>): <span class="title">void</span></span>;</span><br></pre></td></tr></table></figure>

<p><em>应该</em>只使用最大参数个数写一个重载：</p>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/* OK */</span></span><br><span class="line"><span class="keyword">declare</span> <span class="function"><span class="keyword">function</span> <span class="title">beforeAll</span>(<span class="params">action: (done: DoneFn) =&gt; <span class="built_in">void</span>, timeout?: <span class="built_in">number</span></span>): <span class="title">void</span></span>;</span><br></pre></td></tr></table></figure>

<p><em>为什么</em>：回调函数总是可以忽略某个参数的，因此没必要为参数少的情况写重载。 <strong>参数少的回调函数首先允许错误类型的函数被传入，因为它们匹配第一个重载。</strong></p>
<h3 id="函数重载-1"><a href="#函数重载-1" class="headerlink" title="函数重载"></a>函数重载</h3><p>顺序：</p>
<p><em>不要</em>把一般的重载放在精确的重载前面：</p>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/* 错误 */</span></span><br><span class="line"><span class="keyword">declare</span> <span class="function"><span class="keyword">function</span> <span class="title">fn</span>(<span class="params">x: <span class="built_in">any</span></span>): <span class="title">any</span></span>;</span><br><span class="line"><span class="keyword">declare</span> <span class="function"><span class="keyword">function</span> <span class="title">fn</span>(<span class="params">x: HTMLElement</span>): <span class="title">number</span></span>;</span><br><span class="line"><span class="keyword">declare</span> <span class="function"><span class="keyword">function</span> <span class="title">fn</span>(<span class="params">x: HTMLDivElement</span>): <span class="title">string</span></span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> myElem: HTMLDivElement;</span><br><span class="line"><span class="keyword">var</span> x = fn(myElem); <span class="comment">// x: any, wat?</span></span><br></pre></td></tr></table></figure>

<p><em>应该</em>排序重载令精确的排在一般的之前：</p>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/* OK */</span></span><br><span class="line"><span class="keyword">declare</span> <span class="function"><span class="keyword">function</span> <span class="title">fn</span>(<span class="params">x: HTMLDivElement</span>): <span class="title">string</span></span>;</span><br><span class="line"><span class="keyword">declare</span> <span class="function"><span class="keyword">function</span> <span class="title">fn</span>(<span class="params">x: HTMLElement</span>): <span class="title">number</span></span>;</span><br><span class="line"><span class="keyword">declare</span> <span class="function"><span class="keyword">function</span> <span class="title">fn</span>(<span class="params">x: <span class="built_in">any</span></span>): <span class="title">any</span></span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> myElem: HTMLDivElement;</span><br><span class="line"><span class="keyword">var</span> x = fn(myElem); <span class="comment">// x: string, :)</span></span><br></pre></td></tr></table></figure>

<p><em>为什么</em>：TypeScript会选择<em>第一个匹配到的重载</em>当解析函数调用的时候。 当前面的重载比后面的“普通”，那么后面的被隐藏了不会被调用。</p>
<p>使用可选参数：</p>
<p><em>不要</em>为仅在末尾参数不同时写不同的重载：</p>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/* 错误 */</span></span><br><span class="line"><span class="keyword">interface</span> Example &#123;</span><br><span class="line">    diff(one: <span class="built_in">string</span>): <span class="built_in">number</span>;</span><br><span class="line">    diff(one: <span class="built_in">string</span>, two: <span class="built_in">string</span>): <span class="built_in">number</span>;</span><br><span class="line">    diff(one: <span class="built_in">string</span>, two: <span class="built_in">string</span>, three: <span class="built_in">boolean</span>): <span class="built_in">number</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p><em>应该</em>尽可能使用可选参数：</p>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/* OK */</span></span><br><span class="line"><span class="keyword">interface</span> Example &#123;</span><br><span class="line">    diff(one: <span class="built_in">string</span>, two?: <span class="built_in">string</span>, three?: <span class="built_in">boolean</span>): <span class="built_in">number</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>注意这在所有重载都有相同类型的返回值时会不好用。</p>
<p><em>为什么</em>：有以下两个重要原因。</p>
<p>TypeScript解析签名兼容性时会查看是否某个目标签名能够使用源的参数调用， <em>且允许外来参数</em>。 下面的代码暴露出一个bug，当签名被正确的使用可选参数书写时：</p>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">fn</span>(<span class="params">x: (a: <span class="built_in">string</span>, b: <span class="built_in">number</span>, c: <span class="built_in">number</span>) =&gt; <span class="built_in">void</span></span>) </span>&#123; &#125;</span><br><span class="line"><span class="keyword">var</span> x: Example;</span><br><span class="line"><span class="comment">// When written with overloads, OK -- used first overload</span></span><br><span class="line"><span class="comment">// When written with optionals, correctly an error</span></span><br><span class="line">fn(x.diff);</span><br></pre></td></tr></table></figure>

<p>第二个原因是当使用了TypeScript“严格检查null”特性时。 因为没有指定的参数在JavaScript里表示为 <code>undefined</code>，通常显示地为可选参数传入一个<code>undefined</code>。 这段代码在严格null模式下可以工作：</p>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> x: Example;</span><br><span class="line"><span class="comment">// When written with overloads, incorrectly an error because of passing 'undefined' to 'string'</span></span><br><span class="line"><span class="comment">// When written with optionals, correctly OK</span></span><br><span class="line">x.diff(<span class="string">"something"</span>, <span class="literal">true</span> ? <span class="literal">undefined</span> : <span class="string">"hour"</span>);</span><br></pre></td></tr></table></figure>

<p>使用联合类型：</p>
<p><em>不要</em>为仅在某个位置上的参数类型不同的情况下定义重载：</p>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/* WRONG */</span></span><br><span class="line"><span class="keyword">interface</span> Moment &#123;</span><br><span class="line">    utcOffset(): <span class="built_in">number</span>;</span><br><span class="line">    utcOffset(b: <span class="built_in">number</span>): Moment;</span><br><span class="line">    utcOffset(b: <span class="built_in">string</span>): Moment;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p><em>应该</em>尽可能地使用联合类型：</p>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/* OK */</span></span><br><span class="line"><span class="keyword">interface</span> Moment &#123;</span><br><span class="line">    utcOffset(): <span class="built_in">number</span>;</span><br><span class="line">    utcOffset(b: <span class="built_in">number</span>|<span class="built_in">string</span>): Moment;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>注意我们没有让<code>b</code>成为可选的，因为签名的返回值类型不同。</p>
<p><em>为什么</em>：This is important for people who are “passing through” a value to your function:</p>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">fn</span>(<span class="params">x: <span class="built_in">string</span></span>): <span class="title">void</span></span>;</span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">fn</span>(<span class="params">x: <span class="built_in">number</span></span>): <span class="title">void</span></span>;</span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">fn</span>(<span class="params">x: <span class="built_in">number</span>|<span class="built_in">string</span></span>) </span>&#123;</span><br><span class="line">    <span class="comment">// When written with separate overloads, incorrectly an error</span></span><br><span class="line">    <span class="comment">// When written with union types, correctly OK</span></span><br><span class="line">    <span class="keyword">return</span> moment().utcOffset(x);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h1 id="深入"><a href="#深入" class="headerlink" title="深入"></a>深入</h1><h3 id="声明文件原理"><a href="#声明文件原理" class="headerlink" title="声明文件原理"></a>声明文件原理</h3><p>组织模块以提供你想要的API形式保持一致是比较难的。 比如，你可能想要这样一个模块，可以用或不用 <code>new</code>来创建不同的类型， 在不同层级上暴露出不同的命名类型， 且模块对象上还带有一些属性。</p>
<p>阅读这篇指定后，你就会了解如果书写复杂的暴露出友好API的声明文件。 这篇指定针对于模块（UMD）库，因为它们的选择具有更高的可变性。</p>
<p>核心概念：</p>
<p>如果你理解了一些关于TypeScript是如何工作的核心概念， 那么你就能够为任何结构书写声明文件。</p>
<p>类型：</p>
<p>如果你正在阅读这篇指南，你可能已经大概了解TypeScript里的类型指是什么。 明确一下， <em>类型</em>通过以下方式引入：</p>
<ul>
<li>类型别名声明（<code>type sn = number | string;</code>）</li>
<li>接口声明（<code>interface I { x: number[]; }</code>）</li>
<li>类声明（<code>class C { }</code>）</li>
<li>枚举声明（<code>enum E { A, B, C }</code>）</li>
<li>指向某个类型的<code>import</code>声明</li>
</ul>
<p>以上每种声明形式都会创建一个新的类型名称。</p>
<p>值：</p>
<p>与类型相比，你可能已经理解了什么是值。 <strong>值是运行时名字，可以在表达式里引用</strong>。 比如 <code>let x = 5;</code>创建一个名为<code>x</code>的值。</p>
<p>同样，以下方式能够创建值：</p>
<ul>
<li><code>let</code>，<code>const</code>，和<code>var</code>声明</li>
<li>包含值的<code>namespace</code>或<code>module</code>声明</li>
<li><code>enum</code>声明</li>
<li><code>class</code>声明</li>
<li>指向值的<code>import</code>声明</li>
<li><code>function</code>声明</li>
</ul>
<p>命名空间</p>
<p>类型可以存在于<em>命名空间</em>里。 比如，有这样的声明 <code>let x: A.B.C</code>， 我们就认为 <code>C</code>类型来自<code>A.B</code>命名空间。</p>
<p>这个区别虽细微但很重要 – 这里，<code>A.B</code>不是必需的类型或值。</p>
<h4 id="简单的组合：一个名字，多种意义："><a href="#简单的组合：一个名字，多种意义：" class="headerlink" title="简单的组合：一个名字，多种意义："></a><strong>简单的组合：一个名字，多种意义：</strong></h4><p>一个给定的名字<code>A</code>，我们可以找出三种不同的意义：一个类型，一个值或一个命名空间。 要如何去解析这个名字要看它所在的上下文是怎样的。 比如，在声明 <code>let m: A.A = A;</code>， <code>A</code>首先被当做命名空间，然后做为类型名，最后是值。 这些意义最终可能会指向完全不同的声明！</p>
<p>这看上去另人迷惑，但是只要我们不过度的重载这还是很方便的。 下面让我们来看看一些有用的组合行为。</p>
<p>内置组合：</p>
<p>眼尖的读者可能会注意到，比如，<code>class</code>同时出现在<em>类型</em>和<em>值</em>列表里。 <code>class C { }</code>声明创建了两个东西： <em>类型</em><code>C</code>指向类的实例结构， <em>值</em><code>C</code>指向类构造函数。 枚举声明拥有相似的行为。</p>
<p>用户组合：</p>
<p>假设我们写了模块文件<code>foo.d.ts</code>:</p>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">export</span> <span class="keyword">var</span> SomeVar: &#123; a: SomeType &#125;;</span><br><span class="line"><span class="keyword">export</span> <span class="keyword">interface</span> SomeType &#123;</span><br><span class="line">  count: <span class="built_in">number</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>这样使用它：</p>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> * <span class="keyword">as</span> foo <span class="keyword">from</span> <span class="string">'./foo'</span>;</span><br><span class="line"><span class="keyword">let</span> x: foo.SomeType = foo.SomeVar.a;</span><br><span class="line"><span class="built_in">console</span>.log(x.count);</span><br></pre></td></tr></table></figure>

<p>这可以很好地工作，但是我们知道<code>SomeType</code>和<code>SomeVar</code>很相关 因此我们想让他们有相同的名字。 我们可以使用组合通过相同的名字 <code>Bar</code>表示这两种不同的对象（值和对象）：</p>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">export</span> <span class="keyword">var</span> Bar: &#123; a: Bar &#125;;</span><br><span class="line"><span class="keyword">export</span> <span class="keyword">interface</span> Bar &#123;</span><br><span class="line">  count: <span class="built_in">number</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>这提供了解构使用的机会：</p>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> &#123; Bar &#125; <span class="keyword">from</span> <span class="string">'./foo'</span>;</span><br><span class="line"><span class="keyword">let</span> x: Bar = Bar.a;</span><br><span class="line"><span class="built_in">console</span>.log(x.count);</span><br></pre></td></tr></table></figure>

<p>再次地，这里我们使用<code>Bar</code>做为类型和值。 注意我们没有声明 <code>Bar</code>值为<code>Bar</code>类型 – 它们是独立的。</p>
<h4 id="高级组合"><a href="#高级组合" class="headerlink" title="高级组合"></a><strong>高级组合</strong></h4><p>有一些声明能够通过多个声明组合。 比如， <code>class C { }</code>和<code>interface C { }</code>可以同时存在并且都可以做为<code>C</code>类型的属性。</p>
<p>只要不产生冲突就是合法的。 一个普通的规则是值总是会和同名的其它值产生冲突除非它们在不同命名空间里， 类型冲突则发生在使用类型别名声明的情况下（ <code>type s = string</code>）， 命名空间永远不会发生冲突。</p>
<p>让我们看看如何使用。</p>
<p>利用<code>interface</code>添加</p>
<p>我们可以使用一个<code>interface</code>往别一个<code>interface</code>声明里添加额外成员：</p>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">interface</span> Foo &#123;</span><br><span class="line">  x: <span class="built_in">number</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// ... elsewhere ...</span></span><br><span class="line"><span class="keyword">interface</span> Foo &#123;</span><br><span class="line">  y: <span class="built_in">number</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">let</span> a: Foo = ...;</span><br><span class="line"><span class="built_in">console</span>.log(a.x + a.y); <span class="comment">// OK</span></span><br></pre></td></tr></table></figure>

<p>这同样作用于类：</p>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> Foo &#123;</span><br><span class="line">  x: <span class="built_in">number</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// ... elsewhere ...</span></span><br><span class="line"><span class="keyword">interface</span> Foo &#123;</span><br><span class="line">  y: <span class="built_in">number</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">let</span> a: Foo = ...;</span><br><span class="line"><span class="built_in">console</span>.log(a.x + a.y); <span class="comment">// OK</span></span><br></pre></td></tr></table></figure>

<p>注意我们不能使用接口往类型别名里添加成员（<code>type s = string;</code>）</p>
<p>使用<code>namespace</code>添加</p>
<p><code>namespace</code>声明可以用来添加新类型，值和命名空间，只要不出现冲突。</p>
<p>比如，我们可能添加静态成员到一个类：</p>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> C &#123;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// ... elsewhere ...</span></span><br><span class="line"><span class="keyword">namespace</span> C &#123;</span><br><span class="line">  <span class="keyword">export</span> <span class="keyword">let</span> x: <span class="built_in">number</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">let</span> y = C.x; <span class="comment">// OK</span></span><br></pre></td></tr></table></figure>

<p>注意在这个例子里，我们添加一个值到<code>C</code>的<em>静态</em>部分（它的构造函数）。 这里因为我们添加了一个 <em>值</em>，且其它值的容器是另一个值 （类型包含于命名空间，命名空间包含于另外的命名空间）。</p>
<p>我们还可以给类添加一个命名空间类型：</p>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> C &#123;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// ... elsewhere ...</span></span><br><span class="line"><span class="keyword">namespace</span> C &#123;</span><br><span class="line">  <span class="keyword">export</span> <span class="keyword">interface</span> D &#123; &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">let</span> y: C.D; <span class="comment">// OK</span></span><br></pre></td></tr></table></figure>

<p>在这个例子里，直到我们写了<code>namespace</code>声明才有了命名空间<code>C</code>。 做为命名空间的 <code>C</code>不会与类创建的值<code>C</code>或类型<code>C</code>相互冲突。</p>
<p>最后，我们可以进行不同的合并通过<code>namespace</code>声明。 Finally, we could perform many different merges using <code>namespace</code> declarations. This isn’t a particularly realistic example, but shows all sorts of interesting behavior:</p>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">namespace</span> X &#123;</span><br><span class="line">  <span class="keyword">export</span> <span class="keyword">interface</span> Y &#123; &#125;</span><br><span class="line">  <span class="keyword">export</span> <span class="keyword">class</span> Z &#123; &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// ... elsewhere ...</span></span><br><span class="line"><span class="keyword">namespace</span> X &#123;</span><br><span class="line">  <span class="keyword">export</span> <span class="keyword">var</span> Y: <span class="built_in">number</span>;</span><br><span class="line">  <span class="keyword">export</span> <span class="keyword">namespace</span> Z &#123;</span><br><span class="line">    <span class="keyword">export</span> <span class="keyword">class</span> C &#123; &#125;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">type</span> X = <span class="built_in">string</span>;</span><br></pre></td></tr></table></figure>

<p>在这个例子里，第一个代码块创建了以下名字与含义：</p>
<ul>
<li>一个值<code>X</code>（因为<code>namespace</code>声明包含一个值，<code>Z</code>）</li>
<li>一个命名空间<code>X</code>（因为<code>namespace</code>声明包含一个值，<code>Z</code>）</li>
<li>在命名空间<code>X</code>里的类型<code>Y</code></li>
<li>在命名空间<code>X</code>里的类型<code>Z</code>（类的实例结构）</li>
<li>值<code>X</code>的一个属性值<code>Z</code>（类的构造函数）</li>
</ul>
<p>第二个代码块创建了以下名字与含义：</p>
<ul>
<li>值<code>Y</code>（<code>number</code>类型），它是值<code>X</code>的一个属性</li>
<li>一个命名空间<code>Z</code></li>
<li>值<code>Z</code>，它是值<code>X</code>的一个属性</li>
<li>在<code>X.Z</code>命名空间下的类型<code>C</code></li>
<li>值<code>X.Z</code>的一个属性值<code>C</code></li>
<li>类型<code>X</code></li>
</ul>
<p>使用<code>export =</code>或<code>import</code></p>
<p>一个重要的原则是<code>export</code>和<code>import</code>声明会导出或导入目标的<em>所有含义</em>。</p>
<h1 id="发布"><a href="#发布" class="headerlink" title="发布"></a>发布</h1><p>现在我们已经按照指南里的步骤写好一个声明文件，是时候把它发布到npm了。 有两种主要方式用来发布声明文件到npm：</p>
<ol>
<li>与你的npm包捆绑在一起，或</li>
<li>发布到npm上的<a href="https://www.npmjs.com/~types" target="_blank" rel="noopener">@types organization</a>。</li>
</ol>
<p>如果你能控制要使用你发布的声明文件的那个npm包的话，推荐第一种方式。 这样的话，你的声明文件与JavaScript总是在一起传递。</p>
<p>如果你的包有一个主<code>.js</code>文件，你还是需要在<code>package.json</code>里指定主声明文件。 设置 <code>types</code>属性指向捆绑在一起的声明文件。 比如：</p>
<figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">&#123;</span><br><span class="line">    <span class="attr">"name"</span>: <span class="string">"awesome"</span>,</span><br><span class="line">    <span class="attr">"author"</span>: <span class="string">"Vandelay Industries"</span>,</span><br><span class="line">    <span class="attr">"version"</span>: <span class="string">"1.0.0"</span>,</span><br><span class="line">    <span class="attr">"main"</span>: <span class="string">"./lib/main.js"</span>,</span><br><span class="line">    <span class="attr">"types"</span>: <span class="string">"./lib/main.d.ts"</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>注意<code>&quot;typings&quot;</code>与<code>&quot;types&quot;</code>具有相同的意义，也可以使用它。</p>
<p>同样要注意的是如果主声明文件名是<code>index.d.ts</code>并且位置在包的根目录里（与<code>index.js</code>并列），你就不需要使用<code>&quot;types&quot;</code>属性指定了。</p>
<h3 id="依赖"><a href="#依赖" class="headerlink" title="依赖"></a>依赖</h3><p>所有的依赖是由npm管理的。 确保所依赖的声明包都在 <code>package.json</code>的<code>&quot;dependencies&quot;</code>里指明了 比如，假设我们写了一个包它依赖于Browserify和TypeScript。</p>
<figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">&#123;</span><br><span class="line">    <span class="attr">"name"</span>: <span class="string">"browserify-typescript-extension"</span>,</span><br><span class="line">    <span class="attr">"author"</span>: <span class="string">"Vandelay Industries"</span>,</span><br><span class="line">    <span class="attr">"version"</span>: <span class="string">"1.0.0"</span>,</span><br><span class="line">    <span class="attr">"main"</span>: <span class="string">"./lib/main.js"</span>,</span><br><span class="line">    <span class="attr">"types"</span>: <span class="string">"./lib/main.d.ts"</span>,</span><br><span class="line">    <span class="attr">"dependencies"</span>: &#123;</span><br><span class="line">        <span class="attr">"browserify"</span>: <span class="string">"latest"</span>,</span><br><span class="line">        <span class="attr">"@types/browserify"</span>: <span class="string">"latest"</span>,</span><br><span class="line">        <span class="attr">"typescript"</span>: <span class="string">"next"</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>这里，我们的包依赖于<code>browserify</code>和<code>typescript</code>包。 <code>browserify</code>没有把它的声明文件捆绑在它的npm包里，所以我们需要依赖于<code>@types/browserify</code>得到它的声明文件。 <code>typescript</code>相反，它把声明文件放在了npm包里，因此我们不需要依赖额外的包。</p>
<p>我们的包要从这两个包里暴露出声明文件，因此<code>browserify-typescript-extension</code>的用户也需要这些依赖。 正因此，我们使用 <code>&quot;dependencies&quot;</code>而不是<code>&quot;devDependencies&quot;</code>，否则用户将需要手动安装那些包。 如果我们只是在写一个命令行应用，并且我们的包不会被当做一个库使用的话，那么我就可以使用 <code>devDependencies</code>。</p>
<h3 id="危险信号"><a href="#危险信号" class="headerlink" title="危险信号"></a>危险信号</h3><p><code>/// &lt;reference path=&quot;...&quot; /&gt;</code></p>
<p><em>不要</em>在声明文件里使用<code>/// &lt;reference path=&quot;...&quot; /&gt;</code>。</p>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/// &lt;reference path="../typescript/lib/typescriptServices.d.ts" /&gt;</span></span><br><span class="line">....</span><br></pre></td></tr></table></figure>

<p><em>应该</em>使用<code>/// &lt;reference types=&quot;...&quot; /&gt;</code>代替</p>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/// &lt;reference types="typescript" /&gt;</span></span><br><span class="line">....</span><br></pre></td></tr></table></figure>

<p>务必阅读<a href="https://www.tslang.cn/docs/handbook/declaration-files/library-structures.html#consuming-dependencies" target="_blank" rel="noopener">使用依赖</a>一节了解详情。</p>
<h3 id="打包所依赖的声明"><a href="#打包所依赖的声明" class="headerlink" title="打包所依赖的声明"></a>打包所依赖的声明</h3><p>如果你的类型声明依赖于另一个包：</p>
<ul>
<li><em>不要</em>把依赖的包放进你的包里，保持它们在各自的文件里。</li>
<li><em>不要</em>将声明拷贝到你的包里。</li>
<li><em>应该</em>依赖于npm类型声明包，如果依赖包没包含它自己的声明的话。</li>
</ul>
<h3 id="公布你的声明文件"><a href="#公布你的声明文件" class="headerlink" title="公布你的声明文件"></a>公布你的声明文件</h3><p>在发布声明文件包之后，确保在<a href="https://github.com/DefinitelyTyped/DefinitelyTyped/blob/types-2.0/notNeededPackages.json" target="_blank" rel="noopener">DefinitelyTyped外部包列表</a>里面添加一条引用。 这可以让查找工具知道你的包提供了自己的声明文件。</p>
<h3 id="发布到-types"><a href="#发布到-types" class="headerlink" title="发布到@types"></a>发布到<a href="https://www.npmjs.com/~types" target="_blank" rel="noopener">@types</a></h3><p><a href="https://www.npmjs.com/~types" target="_blank" rel="noopener">@types</a>下面的包是从<a href="https://github.com/DefinitelyTyped/DefinitelyTyped" target="_blank" rel="noopener">DefinitelyTyped</a>里自动发布的，通过 <a href="https://github.com/Microsoft/types-publisher" target="_blank" rel="noopener">types-publisher工具</a>。 如果想让你的包发布为@types包，提交一个pull request到<a href="https://github.com/DefinitelyTyped/DefinitelyTyped%E3%80%82" target="_blank" rel="noopener">https://github.com/DefinitelyTyped/DefinitelyTyped。</a> 在这里查看详细信息 <a href="http://definitelytyped.org/guides/contributing.html" target="_blank" rel="noopener">contribution guidelines page</a>。</p>
<h1 id="使用"><a href="#使用" class="headerlink" title="使用"></a>使用</h1><p>在TypeScript 2.0，获取、使用和查找声明文件变得十分容易。 这篇文章将详细说明怎么做这三件事。</p>
<h2 id="下载"><a href="#下载" class="headerlink" title="下载"></a>下载</h2><p>在TypeScript 2.0以上的版本，获取类型声明文件只需要使用npm。</p>
<p>比如，获取lodash库的声明文件，只需使用下面的命令：</p>
<figure class="highlight cmd"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm install --save @types/lodash</span><br></pre></td></tr></table></figure>

<p>如果一个npm包像<a href="https://www.tslang.cn/docs/handbook/declaration-files/publishing.html" target="_blank" rel="noopener">发布</a>里所讲的一样已经包含了它的声明文件，那就不必再去下载相应的<code>@types</code>包了。</p>
<p>下载完后，就可以直接在TypeScript里使用lodash了。 不论是在模块里还是全局代码里使用。</p>
<p>比如，你已经<code>npm install</code>安装了类型声明，你可以使用导入：</p>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> * <span class="keyword">as</span> _ <span class="keyword">from</span> <span class="string">"lodash"</span>;</span><br><span class="line">_.padStart(<span class="string">"Hello TypeScript!"</span>, <span class="number">20</span>, <span class="string">" "</span>);</span><br></pre></td></tr></table></figure>

<p>或者如果你没有使用模块，那么你只需使用全局的变量<code>_</code>。</p>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">_.padStart(<span class="string">"Hello TypeScript!"</span>, <span class="number">20</span>, <span class="string">" "</span>);</span><br></pre></td></tr></table></figure>

<h2 id="查找"><a href="#查找" class="headerlink" title="查找"></a>查找</h2><p>大多数情况下，类型声明包的名字总是与它们在<code>npm</code>上的包的名字相同，但是有<code>@types/</code>前缀， 但如果你需要的话，你可以在 <a href="https://aka.ms/types%E8%BF%99%E9%87%8C%E6%9F%A5%E6%89%BE%E4%BD%A0%E5%96%9C%E6%AC%A2%E7%9A%84%E5%BA%93%E3%80%82" target="_blank" rel="noopener">https://aka.ms/types这里查找你喜欢的库。</a></p>
<blockquote>
<p>注意：如果你要找的声明文件不存在，你可以贡献一份，这样就方便了下一位要使用它的人。 查看DefinitelyTyped <a href="http://definitelytyped.org/guides/contributing.html" target="_blank" rel="noopener">贡献指南页</a>了解详情。</p>
</blockquote>

    </div>
    
    
    
    
    <div>
      
        <div>
    
        <div style="text-align:center;color: #ccc;font-size:14px;">-------------本文结束<i class="fa fa-paw"></i>感谢您的阅读-------------</div>
    
</div>

      
    </div>
        <div class="reward-container">
  <div>坚持原创技术分享，您的支持将鼓励我继续创作！</div>
  <button onclick="var qr = document.getElementById('qr'); qr.style.display = (qr.style.display === 'none') ? 'block' : 'none';">
    打赏
  </button>
  <div id="qr" style="display: none;">
      
      <div style="display: inline-block;">
        <img src="/images/alipay.png" alt="Li Yudong 支付宝">
        <p>支付宝</p>
      </div>

  </div>
</div>

        

<div>
<ul class="post-copyright">
  <li class="post-copyright-author">
    <strong>本文作者： </strong>Li Yudong
  </li>
  <li class="post-copyright-link">
    <strong>本文链接：</strong>
    <a href="http://example.com/2021/12/02/%E7%9B%92%E9%A9%AC%E6%8A%80%E6%9C%AF%E6%A0%88%E5%88%9D%E5%AD%A6/typeScript%E5%A3%B0%E6%98%8E%E6%96%87%E4%BB%B6/" title="TypeScript声明文件">http://example.com/2021/12/02/盒马技术栈初学/typeScript声明文件/</a>
  </li>
  <li class="post-copyright-license">
    <strong>版权声明： </strong>本博客所有文章除特别声明外，均采用 <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/" rel="noopener" target="_blank"><i class="fab fa-fw fa-creative-commons"></i>BY-NC-SA</a> 许可协议。转载请注明出处！
  </li>
</ul>
</div>

    
      <footer class="post-footer">
          <div class="post-tags">
              <a href="/tags/%E5%85%AC%E5%8F%B8%E6%8A%80%E6%9C%AF%E6%A0%88/" rel="tag"># 公司技术栈</a>
          </div>
    
        

    
        
    <div class="post-nav">
      <div class="post-nav-item">
    <a href="/2021/12/01/%E7%9B%92%E9%A9%AC%E6%8A%80%E6%9C%AF%E6%A0%88%E5%88%9D%E5%AD%A6/typeScript%E5%88%9D%E5%AD%A6/" rel="prev" title="typeScript初学">
      <i class="fa fa-chevron-left"></i> typeScript初学
    </a></div>
      <div class="post-nav-item">
    <a href="/2021/12/02/%E7%9B%92%E9%A9%AC%E6%8A%80%E6%9C%AF%E6%A0%88%E5%88%9D%E5%AD%A6/typeScript%E9%A1%B9%E7%9B%AE%E9%85%8D%E7%BD%AE/" rel="next" title="TypeScript项目配置">
      TypeScript项目配置 <i class="fa fa-chevron-right"></i>
    </a></div>
    </div>
      </footer>
    
  </article>
  
  
  



          </div>
          

<script>
  window.addEventListener('tabs:register', () => {
    let { activeClass } = CONFIG.comments;
    if (CONFIG.comments.storage) {
      activeClass = localStorage.getItem('comments_active') || activeClass;
    }
    if (activeClass) {
      let activeTab = document.querySelector(`a[href="#comment-${activeClass}"]`);
      if (activeTab) {
        activeTab.click();
      }
    }
  });
  if (CONFIG.comments.storage) {
    window.addEventListener('tabs:click', event => {
      if (!event.target.matches('.tabs-comment .tab-content .tab-pane')) return;
      let commentClass = event.target.classList[1];
      localStorage.setItem('comments_active', commentClass);
    });
  }
</script>

        </div>
          
  
  <div class="toggle sidebar-toggle">
    <span class="toggle-line toggle-line-first"></span>
    <span class="toggle-line toggle-line-middle"></span>
    <span class="toggle-line toggle-line-last"></span>
  </div>

  <aside class="sidebar">
    <div class="sidebar-inner">

      <ul class="sidebar-nav motion-element">
        <li class="sidebar-nav-toc">
          文章目录
        </li>
        <li class="sidebar-nav-overview">
          站点概览
        </li>
      </ul>

      <!--noindex-->
      <div class="post-toc-wrap sidebar-panel">
          <div class="post-toc motion-element"><ol class="nav"><li class="nav-item nav-level-1"><a class="nav-link" href="#前言"><span class="nav-number">1.</span> <span class="nav-text">前言</span></a></li><li class="nav-item nav-level-1"><a class="nav-link" href="#结构"><span class="nav-number">2.</span> <span class="nav-text">结构</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#识别库的类型"><span class="nav-number">2.1.</span> <span class="nav-text">识别库的类型</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#使用依赖"><span class="nav-number">2.2.</span> <span class="nav-text">使用依赖</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#补充说明"><span class="nav-number">2.3.</span> <span class="nav-text">补充说明</span></a></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#举例"><span class="nav-number">3.</span> <span class="nav-text">举例</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#例子"><span class="nav-number">3.1.</span> <span class="nav-text">例子</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#全局变量"><span class="nav-number">3.1.1.</span> <span class="nav-text">全局变量</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#全局函数"><span class="nav-number">3.1.2.</span> <span class="nav-text">全局函数</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#带属性的对象"><span class="nav-number">3.1.3.</span> <span class="nav-text">带属性的对象</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#函数重载"><span class="nav-number">3.1.4.</span> <span class="nav-text">函数重载</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#可重用类型（接口）"><span class="nav-number">3.1.5.</span> <span class="nav-text">可重用类型（接口）</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#可重用类型（类型别名）"><span class="nav-number">3.1.6.</span> <span class="nav-text">可重用类型（类型别名）</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#组织类型"><span class="nav-number">3.1.7.</span> <span class="nav-text">组织类型</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#类"><span class="nav-number">3.1.8.</span> <span class="nav-text">类</span></a></li></ol></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#规范"><span class="nav-number">4.</span> <span class="nav-text">规范</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#普通类型"><span class="nav-number">4.0.1.</span> <span class="nav-text">普通类型</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#回调函数类型"><span class="nav-number">4.0.2.</span> <span class="nav-text">回调函数类型</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#函数重载-1"><span class="nav-number">4.0.3.</span> <span class="nav-text">函数重载</span></a></li></ol></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#深入"><span class="nav-number">5.</span> <span class="nav-text">深入</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#声明文件原理"><span class="nav-number">5.0.1.</span> <span class="nav-text">声明文件原理</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#简单的组合：一个名字，多种意义："><span class="nav-number">5.0.1.1.</span> <span class="nav-text">简单的组合：一个名字，多种意义：</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#高级组合"><span class="nav-number">5.0.1.2.</span> <span class="nav-text">高级组合</span></a></li></ol></li></ol></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#发布"><span class="nav-number">6.</span> <span class="nav-text">发布</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#依赖"><span class="nav-number">6.0.1.</span> <span class="nav-text">依赖</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#危险信号"><span class="nav-number">6.0.2.</span> <span class="nav-text">危险信号</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#打包所依赖的声明"><span class="nav-number">6.0.3.</span> <span class="nav-text">打包所依赖的声明</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#公布你的声明文件"><span class="nav-number">6.0.4.</span> <span class="nav-text">公布你的声明文件</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#发布到-types"><span class="nav-number">6.0.5.</span> <span class="nav-text">发布到@types</span></a></li></ol></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#使用"><span class="nav-number">7.</span> <span class="nav-text">使用</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#下载"><span class="nav-number">7.1.</span> <span class="nav-text">下载</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#查找"><span class="nav-number">7.2.</span> <span class="nav-text">查找</span></a></li></ol></li></ol></div>
      </div>
      <!--/noindex-->

      <div class="site-overview-wrap sidebar-panel">
        <div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person">
    <img class="site-author-image" itemprop="image" alt="Li Yudong"
      src="/images/author.jpg">
  <p class="site-author-name" itemprop="name">Li Yudong</p>
  <div class="site-description" itemprop="description"></div>
</div>
<div class="site-state-wrap motion-element">
  <nav class="site-state">
      <div class="site-state-item site-state-posts">
          <a href="/archives/">
        
          <span class="site-state-item-count">95</span>
          <span class="site-state-item-name">日志</span>
        </a>
      </div>
      <div class="site-state-item site-state-categories">
            <a href="/categories/">
          
        <span class="site-state-item-count">14</span>
        <span class="site-state-item-name">分类</span></a>
      </div>
      <div class="site-state-item site-state-tags">
            <a href="/tags/">
          
        <span class="site-state-item-count">18</span>
        <span class="site-state-item-name">标签</span></a>
      </div>
  </nav>
</div>
  <div class="links-of-author motion-element">
      <span class="links-of-author-item">
        <a href="https://github.com/tiarmor1" title="GitHub → https:&#x2F;&#x2F;github.com&#x2F;tiarmor1" rel="noopener" target="_blank"><i class="fab fa-github fa-fw"></i>GitHub</a>
      </span>
      <span class="links-of-author-item">
        <a href="mailto:1157019137@qq.com" title="E-Mail → mailto:1157019137@qq.com" rel="noopener" target="_blank"><i class="fa fa-envelope fa-fw"></i>E-Mail</a>
      </span>
  </div>
  <div class="cc-license motion-element" itemprop="license">
    <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/" class="cc-opacity" rel="noopener" target="_blank"><img src="/images/cc-by-nc-sa.svg" alt="Creative Commons"></a>
  </div>



      </div>

    </div>
  </aside>
  <div id="sidebar-dimmer"></div>


      </div>
    </main>

    <footer class="footer">
      <div class="footer-inner">
        

        

<div class="copyright">
  
  &copy; 2020 – 
  <span itemprop="copyrightYear">2022</span>
  <span class="with-love">
    <i class="fa fa-heart"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">Li Yudong</span>
</div>

        








      </div>
    </footer>
  </div>

  
  
  <script color='0,0,0' opacity='0.5' zIndex='-1' count='150' src="/lib1/canvas-nest/canvas-nest.min.js"></script>
  <script src="/lib1/anime.min.js"></script>
  <script src="/lib1/velocity/velocity.min.js"></script>
  <script src="/lib1/velocity/velocity.ui.min.js"></script>

<script src="/js/utils.js"></script>

<script src="/js/motion.js"></script>


<script src="/js/schemes/pisces.js"></script>


<script src="/js/next-boot.js"></script>




  




  
<script src="/js/local-search.js"></script>













  

  

  
   <canvas class="fireworks" style="position: fixed;left: 0;top: 0;z-index: 1; pointer-events: none;" ></canvas> 
   <script type="text/javascript" src="//cdn.bootcss.com/animejs/2.2.0/anime.min.js"></script> 
   <script type="text/javascript" src="/js/fireworks.js"></script>
  
</body>
</html>

